﻿
using GameFramework.UI;
using LS.DataTable;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using UnityGameFramework.Runtime;

namespace LS.UI
{
    public static class UIExtension
    {
        public static IEnumerator FadeToAlpha(this CanvasGroup canvasGroup, float alpha, float duration, bool fadeWithoutTimeScale = false)
        {
            float time = 0f;
            float originalAlpha = canvasGroup.alpha;
            while (time < duration)
            {
                time += fadeWithoutTimeScale ? Time.deltaTime : Time.unscaledDeltaTime;
                canvasGroup.alpha = Mathf.Lerp(originalAlpha, alpha, time / duration);
                yield return new WaitForEndOfFrame();
            }

            canvasGroup.alpha = alpha;
        }

        public static IEnumerator FadeToAlpha(this VisualElement element, float alpha, float duration, bool fadeWithoutTimeScale = false)
        {
            float time = 0f;
            float originalAlpha = element.style.opacity.value;
            while (time < duration)
            {
                time += fadeWithoutTimeScale ? Time.deltaTime : Time.unscaledDeltaTime;
                element.style.opacity = Mathf.Lerp(originalAlpha, alpha, time / duration);
                yield return new WaitForEndOfFrame();
            }

            element.style.opacity = alpha;
        }

        public static IEnumerator SmoothValue(this UnityEngine.UI.Slider slider, float value, float duration, bool fadeWithoutTimeScale = false)
        {
            float time = 0f;
            float originalValue = slider.value;
            while (time < duration)
            {
                time += fadeWithoutTimeScale ? Time.deltaTime : Time.unscaledDeltaTime;
                slider.value = Mathf.Lerp(originalValue, value, time / duration);
                yield return new WaitForEndOfFrame();
            }

            slider.value = value;
        }

        public static bool HasUIForm(this UIComponent uiComponent, UIFormId uiFormId, string uiGroupName = null)
        {
            return uiComponent.HasUIForm((int)uiFormId, uiGroupName);
        }

        public static bool HasUIForm(this UIComponent uiComponent, int uiFormId, string uiGroupName = null)
        {
            var dtUIForm = LSEntry.DataTable.GetDataTable(LSEntry.LSBase.m_DataTableDefaultSetting.UIFormDataType);
            IUIFormData drUIForm = dtUIForm.GetDataRowObject(uiFormId) as IUIFormData;
            if (drUIForm == null)
            {
                return false;
            }

            string assetName = LSPath.FormatUIFormUnityAsset(drUIForm.AssetName);
            if (string.IsNullOrEmpty(uiGroupName))
            {
                return uiComponent.HasUIForm(assetName);
            }

            IUIGroup uiGroup = uiComponent.GetUIGroup(uiGroupName);
            if (uiGroup == null)
            {
                return false;
            }

            return uiGroup.HasUIForm(assetName);
        }

        public static UIFormLogic GetUIForm(this UIComponent uiComponent, UIFormId uiFormId, string uiGroupName = null)
        {
            return uiComponent.GetUIForm((int)uiFormId, uiGroupName);
        }

        public static UIFormLogic GetUIForm(this UIComponent uiComponent, int uiFormId, string uiGroupName = null)
        {
            var dataTable = LSEntry.DataTable.GetDataTable(LSEntry.LSBase.m_DataTableDefaultSetting.UIFormDataType);
            IUIFormData drUIForm = dataTable.GetDataRowObject(uiFormId) as IUIFormData;
            if (drUIForm == null)
            {
                return null;
            }

            string assetName = LSPath.FormatUIFormUnityAsset(drUIForm.AssetName);
            UIForm uiForm = null;
            if (string.IsNullOrEmpty(uiGroupName))
            {
                uiForm = uiComponent.GetUIForm(assetName);
                if (uiForm == null)
                {
                    return null;
                }

                return uiForm.Logic;
            }

            IUIGroup uiGroup = uiComponent.GetUIGroup(uiGroupName);
            if (uiGroup == null)
            {
                return null;
            }

            uiForm = (UIForm)uiGroup.GetUIForm(assetName);
            if (uiForm == null)
            {
                return null;
            }

            return uiForm.Logic;
        }

        public static void CloseUIForm(this UIComponent uiComponent, UIFormLogic uiForm)
        {
            uiComponent.CloseUIForm(uiForm.UIForm);
        }

        public static void CloseUIForm(this UIComponent uiComponent, UIFormId uiFormId)
        {
            var dataTable = LSEntry.DataTable.GetDataTable(LSEntry.LSBase.m_DataTableDefaultSetting.UIFormDataType);
            IUIFormData drUIForm = dataTable.GetDataRowObject((int)uiFormId) as IUIFormData;
            var uiForms = uiComponent.GetUIForms(drUIForm.AssetName);
            foreach (var item in uiForms)
            {
                uiComponent.CloseUIForm(item);
            }
        }

        public static void CloseUIForm(this UIComponent uiComponent, int uiFormId)
        {
            var dataTable = LSEntry.DataTable.GetDataTable(LSEntry.LSBase.m_DataTableDefaultSetting.UIFormDataType);
            IUIFormData drUIForm = dataTable.GetDataRowObject(uiFormId) as IUIFormData;
            var uiForms = uiComponent.GetUIForms(drUIForm.AssetName);
            foreach (var item in uiForms)
            {
                uiComponent.CloseUIForm(item);
            }
        }
        
        public static bool IsLoading(this UIComponent uiComponent, UIFormId uiFormId)
        {
            return uiComponent.IsLoading((int)uiFormId);
        }

        public static bool IsLoading(this UIComponent uiComponent, int uiFormId)
        {
            var dataTable = LSEntry.DataTable.GetDataTable(LSEntry.LSBase.m_DataTableDefaultSetting.UIFormDataType);
            IUIFormData drUIForm = dataTable.GetDataRowObject(uiFormId) as IUIFormData;

            return uiComponent.IsLoadingUIForm(drUIForm.AssetName);
        }

        public static int? OpenUIForm(this UIComponent uiComponent, UIFormId uiFormId, object userData = null)
        {
            return uiComponent.OpenUIForm((int)uiFormId, userData);
        }

        public static int? OpenUIForm(this UIComponent uiComponent, int uiFormId, object userData = null)
        {
            var dataTable = LSEntry.DataTable.GetDataTable(LSEntry.LSBase.m_DataTableDefaultSetting.UIFormDataType);
            IUIFormData drUIForm = dataTable.GetDataRowObject(uiFormId) as IUIFormData;

            if (drUIForm == null)
            {
                Log.Warning("Can not load UI form '{0}' from data table.", uiFormId.ToString());
                return null;
            }
            UIFormParams parm = null;
            if (userData is not null && userData is UIFormParams)
            {
                parm = userData as UIFormParams;
            }
            else
            {
                parm = UIFormParams.Create<UIFormParams>(userData);
            }
            parm.FormId = drUIForm.Id;
            parm.FormName = drUIForm.AssetName;
            parm.AllowMultiInstance = drUIForm.AllowMultiInstance;
            parm.PauseCoveredUIForm = drUIForm.PauseCoveredUIForm;
            
            string assetName = LSPath.FormatUIFormUnityAsset(drUIForm.AssetName);
            if (!drUIForm.AllowMultiInstance)
            {
                if (uiComponent.IsLoadingUIForm(assetName))
                {
                    return null;
                }

                if (uiComponent.HasUIForm(assetName))
                {
                    return null;
                }
            }

            return uiComponent.OpenUIForm(assetName, drUIForm.UIGroupName, Constant.AssetPriority.UIFormAsset, drUIForm.PauseCoveredUIForm, parm);
        }

        public static void OpenMessageBox(this UIComponent uiComponent, MessageBoxParams messageBoxParams)
        {
            uiComponent.OpenUIForm(UIFormId.MessageBoxForm, messageBoxParams);
        }

        public static void OpenOpeningActions(this UIComponent uiComponent, OpeningActionsParams openingActionsParams)
        {
            uiComponent.OpenUIForm(UIFormId.OpeningActionsForm, openingActionsParams);
        }
    }
}
